/*
 * Copyright (c) 2010-2011 Josef Hardi <josef.hardi@gmail.com>
 * Copyright (c) 2010 Piotr Zagawa <piotr.zagawa@gmail.com>
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package id.duapuluhdua.dakidaki.data.tables;

import java.util.Calendar;
import java.util.UUID;

import android.database.Cursor;

import id.duapuluhdua.dakidaki.UserAlert.Result;
import id.duapuluhdua.dakidaki.data.common.DataColumn;
import id.duapuluhdua.dakidaki.data.common.DataRowSet;
import id.duapuluhdua.dakidaki.data.common.DataTable;
import id.duapuluhdua.dakidaki.data.common.DataTableOperation;
import id.duapuluhdua.dakidaki.data.common.DataValues;
import id.duapuluhdua.dakidaki.data.common.Database;
import id.duapuluhdua.dakidaki.data.items.DataItemTrack;
import id.duapuluhdua.dakidaki.service.ServiceCommand;

/**
 *
 */
public class DataTableTracks extends DataTable
{
  /** Constants */
  public final static String tableName = "Tracks";

  public static class column
  {
    public static final int ID = 0;
    public static final int Name = 1;
    public static final int Description = 2;
    public static final int StartTime = 3;
    public static final int EndTime = 4;
    public static final int TotalTime = 5;
    public static final int TotalDistance = 6;
    public static final int Closed = 7;
    public static final int UID = 8;
    public static final int Type = 9;
  };

  private final static DataColumn[] vecTableDefinition =
  {
    new DataColumn(column.ID, DataTable.COL_ID, DataColumn.TYPE_INT, false, true, false),
    new DataColumn(column.Name, "Name", DataColumn.TYPE_TEXT, false, false, true),
    new DataColumn(column.Description, "Description", DataColumn.TYPE_TEXT, true, false, true),
    new DataColumn(column.StartTime, "StartTime", DataColumn.TYPE_INT, false, false, false),
    new DataColumn(column.EndTime, "EndTime", DataColumn.TYPE_INT, false, false, false),
    new DataColumn(column.TotalTime, "TotalTime", DataColumn.TYPE_INT, false, false, false),
    new DataColumn(column.TotalDistance, "TotalDistance", DataColumn.TYPE_INT, false, false, false),
    new DataColumn(column.Closed, "Closed", DataColumn.TYPE_BOOL, false, false, false),
    new DataColumn(column.UID, "UID", DataColumn.TYPE_TEXT, false, false, false),
    new DataColumn(column.Type, "Type", DataColumn.TYPE_INT, false, false, true)
  };

  protected DataRowSet<DataItemTrack> mRows;

  /**
   * @param dataBase
   * @param mTableName
   * @param mVecTableDefinition
   */
  public DataTableTracks(Database database)
  {
    super(database, tableName, vecTableDefinition);
//    rows = new RowSet(this);
  }

  @Override
  public DataValues getNewValues(boolean bForInsert)
  {
    final DataValues values = new DataValues(this);

    // Assign default values if the operation is inserting a new track.
    if (bForInsert) {
      final long timeNowMs = Calendar.getInstance().getTimeInMillis();
      values.setValue(column.StartTime, timeNowMs);
      values.setValue(column.EndTime, timeNowMs);
      values.setValue(column.TotalTime, 0);
      values.setValue(column.TotalDistance, 0);
      values.setValue(column.Closed, false);
      values.setValue(column.UID, UUID.randomUUID().toString());
      values.setValue(column.Type, 0);
    }

    return values;
  }

  public DataItemTrack getTrackItem(long trackId)
  {
    final Cursor cr = getDataRecord(trackId);
    if (cr != null) {
      DataItemTrack item = new DataItemTrack(cr);
      cr.close();
      return item;
    }
    return null;
  }

  /**
   * Gets the current version of table structure.
   *
   * @return a version number.
   */
  @Override
  public int getTableVersion()
  {
    return 1;
  }

  /**
   * Returns a track item that can be resumed or paused.
   *
   * @return
   */
  public DataItemTrack getOpenTrackItem()
  {
    final String where = String.format("%s = 0", getColumnName(column.Closed));

    final Cursor cr = getDataRecords(where);
    if (cr != null) {
      DataItemTrack item = new DataItemTrack(cr);
      cr.close();
      return item;
    }

    return null;
  }

  /**
   *
   * @param trackId
   * @return
   */
  public boolean deleteTrack(long trackId)
  {
    final DataTableGeoPoints tableGeoPoints = mDatabase.getTableGeoPoints();

    boolean bSuccess = false;

    mDatabase.transactionBegin();
    try {
      String where = String.format(
          "%s = %s",
          tableGeoPoints.getColumnName(DataTableGeoPoints.column.TrackID),
          Long.toString(trackId));

      boolean bPointsDeleted = false;
      if (tableGeoPoints.getCount(where) == 0) {
        bPointsDeleted = true;
      }
      else {
        bPointsDeleted = tableGeoPoints.dataDelete(where);
      }

      if (bPointsDeleted) {
        if (dataDelete(trackId)) {
          mDatabase.transactionCommit();
          bSuccess = true;
        }
      }
    }
    finally {
      mDatabase.transactionEnd();
    }

    if (bSuccess) {
      sendOperation(trackId, DataTableOperation.OP_DELETE);
    }
    return bSuccess;
  }

  /**
   * Updates column TotalTime with time period from now to the last resume.
   *
   * @param trackId
   * @param closeTrack
   * @return
   */
  public boolean pauseRecording(long trackId, boolean closeTrack)
  {
    final DataItemTrack item = getTrackItem(trackId);
    if (!item.isClosed()) {
      DataValues values = new DataValues(this);

      final long timeNowMs = Calendar.getInstance().getTimeInMillis();
      values.setValue(column.EndTime, timeNowMs);

      if (closeTrack) {
        values.setValue(column.Closed, true);
      }
      else { // if not yet closed, or just a pause.
        values.setValue(column.TotalTime, item.getTotalTimeWhenPauseInSeconds());
      }

      if (dataUpdate(values, trackId)) {
        sendOperation(trackId, DataTableOperation.OP_UPDATE,
            ServiceCommand.CMD_TRACK_RECORDING_PAUSE, item.getName());
        return true;
      }
    }
    return false;
  }

  public class RowSet extends DataRowSet<DataItemTrack>
  {
    public RowSet(DataTable table)
    {
      super(table);
    }

    @Override
    protected DataItemTrack getItem(Cursor cr)
    {
      return new DataItemTrack(cr);
    }
  }

  @Override
  public Result validateValues(DataValues values)
  {
    return null;  // TODO assume all OK.
  }
}
